package sample.ui

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import android.view.WindowManager
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.netease.core.R
import kotlinx.coroutines.script.C
import kotlinx.coroutines.script.Controller
import kotlinx.coroutines.script.tes.colorInt
import kotlinx.coroutines.script.tes.dp
import kotlinx.coroutines.script.tes.observe
import kotlinx.coroutines.script.tes.printLog
import kotlinx.coroutines.script.tes.pt
import kotlinx.coroutines.script.tes.readByDisk
import kotlinx.coroutines.script.tes.runOnUIThread
import kotlinx.coroutines.script.tes.writeToDisk

class ConsoleLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs) {
    init {
        LayoutInflater.from(context).inflate(R.layout.ov, this)
    }
    private val windowManager by lazy { context.getSystemService(Context.WINDOW_SERVICE) as WindowManager }
    private val windowParams: WindowManager.LayoutParams get() {
        return WindowManager.LayoutParams().also {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                it.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                it.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
            }
            it.format = PixelFormat.RGBA_8888
            it.flags = (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                    or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL) // 不拦截事件. 可能部分手机无效
            it.gravity = Gravity.START or Gravity.TOP
            it.x = 0.dp
            it.y = provideYByScript()
            it.width = 350.pt //binding.container.layoutParams.width // 690.pt
            it.height = provideHeightByScript()
        }
    }
    private var lastY: Int? = null
    private fun provideYByScript():Int {
        val out = if (Properties.area.isNotEmpty() || Properties.scene == C.S_IMM) 541.pt
        else 400.pt
        lastY = out
        return out
    }
    private fun provideHeightByScript(): Int {
        if (Properties.area.isNotEmpty() || Properties.scene == C.S_IMM) return 159.pt   // 700.pt - 541.pt
        return 300.pt
    }

    private var animator: ValueAnimator? = null


    private fun updateRect() {
        val last = lastY
        if (provideYByScript() != last) {
            removeFromWindow()
            windowManager.addView(this, windowParams)
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
//        output.observe(this) {
//            binding.output.text = it
//            binding.output.tag = it
//        }
        Controller.isInvalid.observe(this) {
            stopAnimation()
//            binding.output.alpha = if (it == true) 0.5f else 1f
        }


    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        stopAnimation()
    }

    private fun removeFromWindow() {
        if (isAttachedToWindow) windowManager.removeView(this)
    }

    private fun setOutputTextVisibleTrue() {
//        binding.output.visibility = View.VISIBLE
    }
    private fun setOutputTextVisibleFalse() {
//        binding.time.visibility = View.GONE
//        binding.output.visibility = View.GONE
    }

    private fun startAnimation() {
        animator?.cancel()
        animator = ValueAnimator.ofFloat(1f, 0.5f).apply {
            repeatCount = 2
            repeatMode = ValueAnimator.REVERSE
            interpolator = AccelerateDecelerateInterpolator()
            duration = 1500
            addUpdateListener {
                alpha = (it.animatedValue as Float)
            }
        }
        animator?.start()
    }

    private fun stopAnimation() {
        animator?.cancel()
        alpha = 1f
    }

    companion object {
        private val lock = Any()
//        private var accessibilityError: Boolean? = null
        private var stoppedByScreenOff: Boolean? = null
        private val message = MutableLiveData<String>()
        const val W = "#BBBBBB"

        val output: LiveData<String> = message
        fun outputText(value: CharSequence, color: Int = W.colorInt) {
            synchronized(lock) {
                if (stoppedByScreenOff == null) {
                    stoppedByScreenOff = readByDisk("stoppedByScreenOff")?.toBooleanStrictOrNull() ?: false
                }
                val output = when (stoppedByScreenOff) {
                    true -> "存在熄幕行为.重点开始"
                    else -> value.trim()
                }
                if (output.isNotEmpty()) {
//                    OutputViewV2.append(Spanner().also {
//                        it.append(
//                            output,
//                            ForegroundColorSpan(color)
//                        )
//                    })
                }
            }
        }


        private var outputView: ConsoleLayout? = null
        fun initialize(context: Context?) {
            if (!Properties.displayLog) {
                printLog { "不显示左侧日志" }
                release()
            } else if (context != null) {
                if (outputView == null) ConsoleLayout(context).also { outputView = it }
                outputView?.updateRect()
                outputView?.setOutputTextVisibleTrue()
            }
        }

        fun release() {
            outputView?.removeFromWindow().also { outputView = null }
        }

        fun markStoppedByScreenOff(stopped: Boolean) {
            if (stoppedByScreenOff != stopped) {
                stoppedByScreenOff = stopped
                writeToDisk("stoppedByScreenOff", stopped.toString())
            }
        }

        fun setVisibleFalse() = runOnUIThread {
            outputView?.setOutputTextVisibleFalse()
        }

        fun setVisibleTrue()  = runOnUIThread {
            outputView?.setOutputTextVisibleTrue()
        }
    }
}